import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios'
import store from '@/store/'
import { Message } from 'element-ui'
import router from '@/router/'
import qs from 'qs'
import { config } from 'vue/types/umd'

const request:AxiosInstance = axios.create({

})

const setRequestHead = (config:AxiosRequestConfig) => {
  const { userToken } = store.state
  if (userToken && userToken.access_token) {
    (config.headers as AxiosRequestHeaders).Authorization =
    userToken.access_token
  }
}

function redirectLogin () {
  router.push({
    name: 'login',
    query: { redirect: router.currentRoute.fullPath }
  })
}

function refreshToken () {
  return axios.create()({
    method: 'POST',
    url: '/front/user/refresh_token',
    data: qs.stringify({ // 处理为 x-www
      refreshtoken: store.state.userToken.refresh_token
    })
  })
}

request.interceptors.request.use((config:AxiosRequestConfig) => {
  console.log('configrequest', config)
  store.commit('addAxiosShowLoading')
  setRequestHead(config)
  return config
}, (error:AxiosError) => {
  console.dir(error)
  store.commit('errorAxiosShowLoading')
  return Promise.reject(error)
})

let isRefreshing = false
let requestArr = <any[]>[]
request.interceptors.response.use((config:AxiosResponse) => {
  // 真实状态码为 200的进入
  console.log('configresponse', config)
  store.commit('removeAxiosShowLoading')
  return config
}, (error:AxiosError) => {
  console.dir(error)
  store.commit('errorAxiosShowLoading')
  if (error.response) {
    // 收到响应了
    if (error.response.status === 400) {
      Message.error('请求参数错误')
    } else if (error.response.status === 401) {
      // 1. vuex内没有 token 信息
      // 2. 有token信息，但是不正确，需要刷新token
      if (!store.state.userToken) {
        redirectLogin()
        return Promise.reject(error)
      }
      if (!isRefreshing) {
        isRefreshing = true
        return refreshToken().then(res => {
          if (!res.data.success) {
            throw new Error('刷新失败')
          }
          store.commit('setUserToken', res.data.content)
          requestArr.forEach(cb => cb())
          requestArr = []
          return request(error.config)
        }).catch(() => {
          store.commit('setUserToken', 'null')
          redirectLogin()
          return Promise.reject(error)
        }).finally(() => {
          isRefreshing = false
        })
      }
      // eslint-disable-next-line promise/param-names
      return new Promise(res => {
        requestArr.push(() => {
          res(request(error.config))
        })
      })
    } else if (error.response.status === 403) {
      Message.error('没有权限，请联系管理员')
    } else if (error.response.status === 404) {
      Message.error('请求资源不存在')
    } else if (error.response.status >= 500) {
      Message.error('服务端错误，请联系管理员')
    }
  } else if (error.request) {
    // 发出请求了，没收到响应
    Message.error('请求超时，请刷新重试')
  } else {
    // 其他未知错误
    Message.error('请求失败:' + error.message)
  }
  return Promise.reject(error)
})

export default <T>(config:AxiosRequestConfig) => {
  return request(config).then(res => (res.data.data || res.data) as T)
}
